/**
 *  JS 公共实用工具
 */
let zmnMothedUtil = {
    /**
     * 删除对象的空属性
     * @param object 需处理的对象
     * @author DaiZhichao
     */
    deleteEmptyProperty: function (object) {
        for (var i in object) {
            var value = object[i];
            if (typeof value === 'object') {
                if (Array.isArray(value)) {
                    if (value.length == 0) {
                        delete object[i];
                        continue;
                    }
                }
                this.deleteEmptyProperty(value);
                if (this.isEmpty(value)) {
                    delete object[i];
                }
            } else {
                if (value === '' || value === null || value === undefined) {
                    delete object[i];
                } else {
                }
            }
        }
    },
    /**
     * 数组去重
     * @author DaiZhichao
     * @param array 去重前的数组
     * @return {Array} 去重后的数组
     */
    uniq: function (array) {
        var temp = []; //一个新的临时数组
        for (var i = 0; i < array.length; i++) {
            if (temp.indexOf(array[i]) == -1) {
                temp.push(array[i]);
            }
        }
        return temp;
    },
    /**
     * 将一个对象转为GET参数
     * @author DaiZhichao
     * @param obj 对象
     */
    serializeFormObj: function (obj) {
        let str = "?";
        for (let property in obj) {
            if (!(obj[property] === null || obj[property] === "")) {
                str = str + property + "=" + obj[property] + "&";
            }
        }
        if (str.endsWith("&")) {
            str = str.substring(0, str.length - 1);
        }
        return str;
    },
    /**
     * 将一个对象转为GET参数
     * @author DaiZhichao
     * @param $form jq表单对象
     */
    serialize: function ($form) {
        let arr1 = $form.serializeArray();
        return arr1.reduce((previousValue, currentValue, currentIndex, array) => {
            if (currentValue.value !== "") {
                previousValue = previousValue + currentValue.name + "=" + currentValue.value + "&";
            }
            if (currentIndex === array.length - 1) {
                previousValue = previousValue.substring(0, previousValue.length - 1);
            }
            return previousValue;
        }, "?");
    },
    timeDifferenceFormater: function (timeoutTime, timeFormater = "dd天 hh时 mm分 ss秒") {
        let days = Math.floor(timeoutTime / (1000 * 60 * 60 * 24));
        let hours = Math.floor(timeoutTime / (1000 * 60 * 60)) % 24;
        let minutes = Math.floor(timeoutTime / (1000 * 60)) % 60;
        let seconds = Math.floor(timeoutTime / 1000) % 60;

        if (days < 1) {
            timeFormater = timeFormater.substring(timeFormater.indexOf("hh"))
        }
        if (days < 1 && hours < 1) {
            timeFormater = timeFormater.substring(timeFormater.indexOf("mm"))
        }
        if (days < 1 && hours < 1 && minutes < 1) {
            timeFormater = timeFormater.substring(timeFormater.indexOf("ss"))
        }
        if (days < 1 && hours < 1 && minutes < 1 && seconds < 1) {
            timeFormater = "时间差格式不正确"
        }
        timeFormater = timeFormater.replace("dd", days).replace("hh", hours).replace("mm", minutes).replace("ss", seconds);
        return timeFormater;
    }
};

/**
 *  Layui 封装实用工具
 */
let zmnLayUtil = {
    /**
     * 【自定义表单验证】Layui-form包装
     *
     * 使用方式：zmnLayUtil.layFormVerify(form);
     * @param form layui.form
     * @param per 对象{
     *     extend:拓展layui验证器
     * }
     */
    layFormVerify: function (form, per) {
        if (per !== undefined) {
            let {maxLengthNumPer, maxLengthVarcharPer, maxLengthTitlePer, maxLengthRemarkPer, extend} = per;
        }
        let defaultPer = {
            maxLengthNumPer: 20
            , maxLengthVarcharPer: 20
            , maxLengthTitlePer: 20
            , maxLengthRemarkPer: 100
        };

        let normalPer = Object.assign({}, defaultPer, per);
        let formVerifyPer = {
            /**
             *  金额验证
             *  正整数，允许两位小数
             *  必定小于1000000
             */
            amount: function (value, item) {
                if (value !== "") {
                    let r = /^([1-9]\d{0,9}|0)([.]?|(\.\d{1,2})?)$/;
                    if (!r.test(value)) {
                        return '格式内容不正确，请重新输入';
                    }
                    if (Number(value) > 1000000) {
                        return '数值不能超过1000000.00';
                    }
                }
            },
            /**
             *  折扣
             *  正整数，允许一位小数
             *  必定小于10
             */
            coupDiscount: function (value, item) {
                if (value !== "") {
                    let r = /^([1-9]\d{0,9}|0)([.]?|(\.\d{1})?)$/;
                    if (!r.test(value)) {
                        return '格式内容不正确，请重新输入';
                    }
                    if (Number(value) >= 10) {
                        return '折扣不能大于等于10.0';
                    }
                }
            }
            ,
            /**
             *  比例
             *  正整数，允许两位小数
             *  必定小于100
             */
            masterConfigDiscount: function (value, item) {
                if (value !== "") {
                    let r = /^([1-9]\d{0,9}|0)([.]?|(\.\d{0,2})?)$/;
                    if (!r.test(value)) {
                        return '格式内容不正确，请重新输入';
                    }
                    if (Number(value) >= 100) {
                        return '比例不能大于等于100';
                    }
                }
            },
            /**
             *  通用百分比比例
             *  正整数，允许两位小数
             *  必定小于等于100
             */
            normalPercent: function (value, item) {
                if (value !== "") {
                    let r = /^([1-9]\d{0,9}|0)([.]?|(\.\d{0,2})?)$/;
                    if (!r.test(value)) {
                        return '格式内容不正确，请重新输入';
                    }
                    if (Number(value) > 100) {
                        return '比例不能大于100';
                    }
                }
            }
            , longNumber: function (value, item) {
                if (value !== "") {
                    if (!zmnRegularExpressionUtil.isInteger(value)) {
                        return "请输入整数";
                    }
                    if (Number(value) > 9223372036854775807 || Number(value) < -9223372036854775808) {
                        return '数字超出限制';
                    }
                }
            },
            /**
             *  正整数，允许一位小数
             *  必定小于1000
             */
            floatPointOne: function (value, item) {
                if (value !== "") {
                    let r = /^([1-9]\d{0,9}|0)([.]?|(\.\d{1})?)$/;
                    if (!r.test(value)) {
                        return '格式内容不正确，请重新输入';
                    }
                    if (Number(value) > 99999999) {
                        return '不能超过99999999';
                    }
                }
            },
            /**
             *  正整数，允许两位小数
             *  必定小于1000
             */
            floatPointTwo: function (value, item) {
                if (value !== "") {
                    let r = /^([1-9]\d{0,9}|0)([.]?|(\.\d{0,2})?)$/;
                    if (!r.test(value)) {
                        return '格式内容不正确，请重新输入';
                    }
                    if (Number(value) > 99999999) {
                        return '不能超过99999999';
                    }
                }
            }
            , isNumber: function (value) {
                if (value !== "") {
                    if (!zmnRegularExpressionUtil.isInteger(value)) {
                        return "请输入整数";
                    }
                }
            }
            , isPositiveNumber: function (value, item) {
                if (value !== "") {
                    if (!zmnRegularExpressionUtil.isNonNegativeInteger(value)) {
                        return '请输入整数';
                    }
                }
            }

            /**
             *  数量验证
             *  正整数
             *  必定小于1000000
             */
            , quantity: function (value, item) {
                if (value !== "") {
                    if (!zmnRegularExpressionUtil.isPositiveInteger(value)) {
                        return '格式内容不正确，请重新输入';
                    }
                    if (Number(value) > 1000000) {
                        return '数量不能超过1000000';
                    }
                }
            }

            /**
             *  百分比验证
             *  正整数
             *  0~100
             */
            , discount: function (value, item) {
                if (value !== "") {
                    if (!zmnRegularExpressionUtil.isPositiveInteger(value)) {
                        return '格式内容不正确，请重新输入';
                    }
                    if (Number(value) > 100) {
                        return '折扣不能超过100%';
                    }
                }
            }
            /**
             *  金额验证，正整数
             *  正整数
             *  必定小于1000000
             */
            , amountPositiveInteger: function (value, item) {
                if (value !== "") {
                    if (!zmnRegularExpressionUtil.isPositiveInteger(value)) {
                        return '格式内容不正确，请重新输入';
                    }
                    if (Number(value) >= 99999999) {
                        return '金额不能超过99999999';
                    }
                }
            }
            /**
             *  输入框非空非零验证
             */
            , noZeroNoNull: function (value, item) {
                if (value == null
                    || Number(value) === 0
                    || value === undefined) {
                    return "请重新输入";
                }
            }
            /**
             *  多级填充时非空非零验证
             */
            , selectNoZeroNoNull: function (value, item) {
                if (value === "") {
                    return "请重新选择";
                }
                if (value == null) {
                    return "请重新选择";
                }
                if (Number(value) === 0) {
                    return "请重新选择";
                }
            }
            , positive: function (value, item) {
                if (value !== "") {
                    if (!zmnRegularExpressionUtil.isPositiveInteger(value)) {
                        return "请输入正整数";
                    }
                }
            }
            , maxLengthNum: function (value) {
                if (value !== "") {
                    if (value.length > normalPer.maxLengthNumPer) {
                        return '长度不能超过' + normalPer.maxLengthNumPer + '个字符！';
                    }
                }
            }
            , maxLengthVarchar: function (value) {
                if (value !== "") {
                    if (value.length > normalPer.maxLengthVarcharPer) {
                        return '长度不能超过' + normalPer.maxLengthVarcharPer + '个字符！';
                    }
                }
            }
            , maxLengthTitle: function (value) {
                if (value !== "") {
                    if (value.length > normalPer.maxLengthTitlePer) {
                        return '长度不能超过' + normalPer.maxLengthTitlePer + '个字符！';
                    }
                }
            }
            , maxLengthRemark: function (value) {
                if (value !== "") {
                    if (value.length > normalPer.maxLengthRemarkPer) {
                        return '长度不能超过' + normalPer.maxLengthRemarkPer + '个字符！';
                    }
                }
            }
            , phone: function (value) {
                if (value !== "") {
                    if (!zmnRegularExpressionUtil.isPhone(value)) {
                        return "电话号码不正确";
                    }
                }
            }
            , tel: function (value) {
                if (value !== "") {
                    if (!zmnRegularExpressionUtil.isPositiveInteger(value)) {
                        return "电话号码不正确";
                    }
                }
            }
            , notZero: function (value) {
                if (value !== "") {
                    if (value == 0 || value == "0" || value < 0) {
                        return "值不能为0或负数";
                    }
                }
            }
            , bankCardNum: function (value) {
                if (value !== "") {
                    if (!zmnRegularExpressionUtil.isBankCardNum(value)) {
                        return "银行卡号格式不正确";
                    }
                }
            }
            , max_2500: function (value, item) {
                if (value !== "") {
                    let r = /^([1-9]\d{0,9}|0)([.]?|(\.\d{1,2})?)$/;
                    if (!r.test(value)) {
                        return '格式内容不正确，请重新输入';
                    }
                    if (Number(value) > 2500) {
                        return '数值不能超过2500.00';
                    }
                    if (Number(value) < 1) {
                        return '数值不能小于1';
                    }
                }
            },


        };
        formVerifyPer = Object.assign({}, formVerifyPer, normalPer.extend);

        form.verify(formVerifyPer);
    }
    /**
     * 多级下拉联动框
     *
     * 请求的格式为 {value:"选择的select的value"} 如：{value:"10001"}
     *
     * @author DaiZhichao
     * @param $ layui.$
     * @param form layui.form
     * @param parameter 参数对象
     * parameter 对象{
     *          option:    启用禁用字段设置对象
     *              {
     *                    enableOnly:   [True]只显示启用的对象 [false]显示全部对象    默认值 [True]
     *                    disableEffect:[True]被禁用对象不可选择 [false]被禁用的对象可以选择   默认值 [True]
     *                    disableText:  [True]被禁用的对象追加(已禁用)字符串
     *                                  [false]被禁用的对象不会追加字符串
     *                                  默认值 [True]
     *              }
     *       selectId1: 第1级select的ID，不含#号
     *       selectUrl1:第1级select的触发的URL，用于加载2级select
     *       selectId2: 第2级select的ID，不含#号
     *       selectUrl2:第2级select的触发的URL，用于加载3级select
     *       selectId3: 第3级select的ID，不含#号
     *       selectUrl3:第3级select的触发的URL，用于加载4级select
     *       selectId4: 第4级select的ID，不含#号
     *              }
     */
    , laySelectLinkage: function ($, form, parameter) {
        let {option, selectId1, selectUrl1, selectId2, selectUrl2, selectId3, selectUrl3, selectId4} = parameter;

        let optionDefault = {
            enableOnly: true
            , disableEffect: true
            , disableText: true
            , defaultSelectedText: "请选择"
        };

        let normalOption = Object.assign({}, optionDefault, option);

        let baseHtml = `<option value="">${normalOption.defaultSelectedText}</option>`;
        form.on("select(" + selectId1 + ")", function (obj) {
            $("#" + selectId4).html(baseHtml);
            $("#" + selectId3).html(baseHtml);
            $("#" + selectId2).html(baseHtml);
            form.render("select");
            if (zmnUtil.isNull(obj) || Number(obj.value) === 0) {
                return false;
            }

            $.ajax({
                type: "POST", url: selectUrl1,
                dataType: "json", data: {value: obj.value}
            }).done(function (items) {
                let tempHtml = baseHtml;
                if (items.length > 0) {
                    if (normalOption.enableOnly) {
                        if (items[0].status) {
                            items = items.filter((value) => {
                                return value.status;
                            })
                        }
                    }

                    items.forEach(items => {
                        let exAttr = "";
                        let exText = "";
                        if (items) {
                            if (!items.status) {
                                if (normalOption.disableEffect) {
                                    exAttr = "disabled";
                                }
                                if (normalOption.disableText) {
                                    exText = "(已禁用)";
                                }
                            }
                        }
                        tempHtml += '<option value="' + items.value + '" ' + exAttr + '>' + items.text + " " + exText + '</option>';
                    });
                }
                $("#" + selectId4).html(baseHtml);
                $("#" + selectId3).html(baseHtml);
                $("#" + selectId2).html(tempHtml);
                form.render("select");
            });
        });

        if (zmnUtil.isEmptyNull(selectUrl2)) {
            return;
        }


        form.on("select(" + selectId2 + ")", function (obj) {
            $("#" + selectId4).html(baseHtml);
            $("#" + selectId3).html(baseHtml);
            form.render("select");
            if (zmnUtil.isNull(obj) || obj.value === 0) {
                return false;
            }
            $.ajax({
                type: "GET", url: selectUrl2,
                dataType: "json", data: {value: obj.value}
            }).done(function (items) {
                let tempHtml = baseHtml;
                if (items.length > 0) {
                    if (normalOption.enableOnly) {
                        if (items[0].status) {
                            items = items.filter((value) => {
                                return value.status;
                            })
                        }
                    }

                    items.forEach(items => {
                        let exAttr = "";
                        let exText = "";
                        if (items) {
                            if (!items.status) {
                                if (normalOption.disableEffect) {
                                    exAttr = "disabled";
                                }
                                if (normalOption.disableText) {
                                    exText = "(已禁用)";
                                }
                            }
                        }
                        tempHtml += '<option value="' + items.value + '" ' + exAttr + '>' + items.text + " " + exText + '</option>';
                    });
                }
                $("#" + selectId3).html(tempHtml);
                $("#" + selectId4).html(baseHtml);
                form.render("select");
            });
        });

        if (zmnUtil.isEmptyNull(selectUrl3)) {
            return;
        }


        form.on("select(" + selectId3 + ")", function (obj) {
            $("#" + selectId4).html(baseHtml);
            form.render("select");
            if (zmnUtil.isNull(obj) || obj.value === 0) {
                return false;
            }
            $.ajax({
                type: "GET", url: selectUrl3,
                dataType: "json", data: {value: obj.value}
            }).done(function (items) {
                let tempHtml = baseHtml;
                if (items.length > 0) {
                    if (normalOption.enableOnly) {
                        if (items[0].status) {
                            items = items.filter((value) => {
                                return value.status;
                            })
                        }
                    }

                    items.forEach(items => {
                        let exAttr = "";
                        let exText = "";
                        if (items) {
                            if (!items.status) {
                                if (normalOption.disableEffect) {
                                    exAttr = "disabled";
                                }
                                if (normalOption.disableText) {
                                    exText = "(已禁用)";
                                }
                            }
                        }
                        tempHtml += '<option value="' + items.value + '" ' + exAttr + '>' + items.text + " " + exText + '</option>';
                    });
                }
                $("#" + selectId4).html(tempHtml);
                form.render("select");
            });
        });
    }

    /**
     * 分页
     * @param laypage
     * @param totalCount 总记录数
     * @param pageSize 每页显示记录数
     * @param pageIndex 当前页
     * @param pageSizeId
     * @param pageIndexId
     * @param pageFormId
     */
    , layPageRender: function (laypage, totalCount, pageSize, pageIndex, pageSizeId, pageIndexId, pageFormId) {
        var $ = layui.$;
        laypage.render({
            elem: 'page'
            , count: totalCount //数据总数，从服务端得到
            , layout: ['count', 'prev', 'page', 'next', 'limit', 'refresh', 'skip']
            , limits: [10, 20, 30, 40, 50]
            , limit: pageSize
            , curr: pageIndex //获取起始页
            , jump: function (obj, first) {
                //obj包含了当前分页的所有参数，比如：
                console.log(obj.curr); //得到当前页，以便向服务端请求对应页的数据。
                console.log(obj.limit); //得到每页显示的条数

                //首次不执行
                if (!first) {
                    //do something
                    $("#" + pageIndexId).val(obj.curr);
                    $("#" + pageSizeId).val(obj.limit);
                    $("#" + pageFormId).submit();
                }
            }
        });
    }
    /**
     * 【关闭当前弹出窗口】Layui-Layer包装
     * @param parent parent   对象
     * @param reloadConfig    父页面刷新配置
     *         {
     *         tableSelector:  父页面表格的lay-filter 可传字符串或数组 如："zmn-aaa-table" 或者["zmn-aaa-table","zmn-bbb-table"]
     *         formSelector:   父页面表单的lay-filter 可传字符串或数组 如："zmn-aaa-form" 或者["zmn-aaa-form","zmn-bbb-form"]
     *                   }
     * @param msgConfig       集成的layui-msg配置  https://www.layui.com/doc/modules/layer.html#layer.msg
     *         {
     *         layer:          可传入layer 或者 parent.layui.layer
     *         msg:            提示信息
     *         icon:           可选图标[0-6]           如：icon: 1
     *         time:           layer.msg存在的时间（如果不配置，默认是3秒）
     *         callback:       弹窗关闭回调
     *                   }
     */
    , closeThisIframe: function (parent, reloadConfig, msgConfig) {
        if (reloadConfig) {
            let {tableSelector, formSelector} = reloadConfig;
        }
        if (msgConfig) {
            let {layer, msg, icon, time, callback} = msgConfig;
        }


        if (msgConfig) {
            msgConfig.layer.msg(
                msgConfig.msg
                , {icon: msgConfig.icon, time: msgConfig.time}
                , msgConfig.callback
            );
        }

        if (reloadConfig) {
            if (reloadConfig.tableSelector) {
                if (!Array.isArray(reloadConfig.tableSelector)) {
                    reloadConfig.tableSelector = new Array(reloadConfig.tableSelector)
                }
                reloadConfig.tableSelector.forEach(value => {
                    parent.layui.table.reload(value);
                });
            }
            if (reloadConfig.formSelector) {
                if (!Array.isArray(reloadConfig.formSelector)) {
                    reloadConfig.formSelector = new Array(reloadConfig.formSelector)
                }
                reloadConfig.formSelector.forEach(value => {
                    parent.layui.form.render(value);
                });
            }
        }

        let index = parent.layer.getFrameIndex(window.name);
        parent.layer.close(index);
    }
    , closeThisIframeMsg: function (parent, msg, parentTableId) {
        if (parentTableId) {
            parent.layui.table.reload(parentTableId);
        }
        //当你在iframe页面关闭自身时
        let index = parent.layer.getFrameIndex(window.name); //先得到当前iframe层的索引
        parent.layer.close(index); //再执行关闭
        if (msg) {
            parent.layer.msg(msg, {"icon": 1});
        }

    }
    , closeThisTabs: function () {
        layui.admin.events.closeThisTabs();
    }
    , closeThisTabsChange: function (tabUrl, parent) {
        console.log('closeThisTabsChange');
        parent.layui.element.tabChange('layadmin-layout-tabs', tabUrl);
        parent.layui.element.tabDelete('layadmin-layout-tabs', window.location.pathname + window.location.search);
    }

    /**
     * 【渲染table】Layui-Layer包装
     * 【异步】使用分页插件 LayuiPage
     *
     * 使用LayuiTableResponseDTO返回
     *
     * @param table layui.table
     * @param cols: 表格列绑定对象
     * @param id
     * @param data
     * @param url: Ajax请求地址
     * @param parameter 扩展参数对象
     *       elem: : 默认会以["#" + id ]形式拼接
     *       toolbar: 默认会以["#" + id + "-tool"]形式拼接
     *       title:  表格标题
     *       data: Ajax请求参数 JSON对象
     *       limit:  初始分页条数 默认值 10
     *       limits:  默认值 [10, 20, 30, 40, 50]
     *       height: 传入 null 可以自适应 默认值 ['full-214']
     *       defaultToolbar: ['filter', 'print', 'exports']
     *       loading: 是否显示加载进度条 默认值[true]
     *       done: 回调函数
     *       page: 是否分页
     *              }
     */
    , layTableRender: function (table, cols, id, data, url, parameter) {
        if (parameter !== undefined) {
            let {height, elem, toolbar, defaultToolbar, title, loading, done, page, skin, even, size, layout} = parameter;
        }
        let defaultParameter = {
            elem: "#" + id
            , toolbar: "#" + id + "-tool"
            , defaultToolbar: ['filter'] // ['filter', 'print', 'exports']
            , loading: true
            , page: {
                prev: "上一页"
                , next: "下一页"
                , hash: true
                , limit: 50
                , limits: [50, 100, 150]
                , layout: ['count', 'prev', 'page', 'next', 'limit', 'refresh', 'skip']
            },

        };

        let normalParameter = Object.assign({}, defaultParameter, parameter);

        table.render({
            id: id
            , url: url
            , where: data
            , cols: cols
            , elem: normalParameter.elem
            , layout: normalParameter.layout
            , defaultToolbar: normalParameter.defaultToolbar
            , toolbar: normalParameter.toolbar
            , title: normalParameter.title
            , limit: (normalParameter.page === true) ? normalParameter.limit : undefined
            , limits: (normalParameter.page === true) ? normalParameter.limits : undefined
            , height: normalParameter.height
            , loading: normalParameter.loading
            , done: normalParameter.done
            , page: normalParameter.page
            , skin: normalParameter.skin
            , even: normalParameter.even
            , size: normalParameter.size
            , request: {
                pageName: 'pageNum' //页码的参数名称，默认：page
                , limitName: 'pageSize' //每页数据量的参数名，默认：limit       //?curr=1&nums=30
            }
            , response: {
                statusName: 'code' //规定数据状态的字段名称，默认：code
                , statusCode: 200 //规定成功的状态码，默认：0
                // ,msgName: 'hint' //规定状态信息的字段名称，默认：msg
                // ,countName: 'total' //规定数据总数的字段名称，默认：count
                // ,dataName: 'rows' //规定数据列表的字段名称，默认：data
            }
        });
    }
    /**
     * 查询按钮
     * @author DaiZhichao
     * @param form
     * @param table
     * @param id
     */
    ,   layTableReload: function (form, table, id, cols, url, data, callback, parameter) {
        var page = parameter != null && parameter.page == false ? false : {curr: 1};
        form.on('submit(query-submit)', function (data) {
            //执行重载
            table.reload(id, {page: page, where: data.field});
            if (callback) {
                callback(data.field);
            }
            return false;
        });
        if (url) {
            this.layTableRender(table, cols, id, data, url);
        }
    }
    /**
     * 逻辑分页
     * @param form
     * @param table
     * @param id
     */
    , layTableReload2: function (form, table, id, cols, url, data, parameter) {
        if (parameter !== undefined) {
            let {height, elem, toolbar, defaultToolbar, title, loading, done, page, skin, even, size, layout} = parameter;
        }
        let defaultParameter = {
            elem: "#" + id
            , toolbar: "#" + id + "-tool"
            , defaultToolbar: ['filter'] // ['filter', 'print', 'exports']
            , limit: 50
            , limits: [50, 100, 150]
            , height: 'full-120'
            , loading: true
            , page: true
        };

        let normalParameter = Object.assign({}, defaultParameter, parameter);
        var call = function (data) {
            //逻辑分页
            zmnLayUtil.ajaxSimpleUE(url, data, 0, function (json) {
                if (json.code == 200) {
                    table.render({
                        elem: normalParameter.elem
                        , layout: normalParameter.layout
                        , defaultToolbar: normalParameter.defaultToolbar
                        , toolbar: normalParameter.toolbar
                        , title: normalParameter.title
                        , limit: (normalParameter.page === true) ? normalParameter.limit : undefined
                        , limits: (normalParameter.page === true) ? normalParameter.limits : undefined
                        , height: normalParameter.height
                        , loading: normalParameter.loading
                        , done: normalParameter.done
                        , page: normalParameter.page
                        , skin: normalParameter.skin
                        , even: normalParameter.even
                        , size: normalParameter.size
                        , data: json.data
                        , extData:json.extData
                        , cols: cols
                    });
                }
            });
        };
        call(data);
        form.on('submit(query-submit)', function (data) {
            call(data.field);
            return false;
        });
    }

    /**
     * 【打开Iframe】Layui-Layer包装
     * @param layer layer对象
     * @param title 窗口标题
     * @param url URL
     */
    , openIframe: function (layer, title, url, callback) {
        console.error("zmnLayUtil.openIframe()方法已过时，请使用zmnLayUtil.openIframeCustom()");
        layer.open({
            type: 2,
            title: title,
            shadeClose: true,
            shade: false,
            maxmin: true, //开启最大化最小化按钮
            area: ['90%', '95%'],
            content: url, //iframe的url，no代表不显示滚动条
            end: callback
        });
    }

    , openIframeCustom: function (layer, url, parameter) {

        if (parameter !== undefined) {
            let {type, title, shadeClose, shade, maxmin, area, content, end, success,id} = parameter;
        }
        let defaultParameter = {
            type: 2,
            title: "",
            shadeClose: true,
            shade: 0,
            time: 0,
            maxmin: true, //开启最大化最小化按钮
            area: ['90%', '95%'],
            end: null,
            idL: null
        };
        let normalParameter = Object.assign({}, defaultParameter, parameter);
        layer.open({
            type: normalParameter.type,
            title: normalParameter.title,
            shadeClose: normalParameter.shadeClose,
            shade: normalParameter.shade,
            maxmin: normalParameter.maxmin,
            area: normalParameter.area,
            content: url,
            end: normalParameter.end,
            success: normalParameter.success,
            id: normalParameter.id
        });
    }
    , openTabsPageCustom: function (parent, url, text, parameter) {
        if (parameter !== undefined) {
            let {} = parameter;
        }
        let defaultParameter = {};
        let normalParameter = Object.assign({}, defaultParameter, parameter);
        parent.layui.index.openTabsPage(url, text);
    }
    /**
     * 【批量 启用/停用】Layui-Table包装
     * @author DaiZhiChao
     * @since 2018-10-29
     * @param url
     * @param ids 数据集合，格式 11,12,32
     * @param callback 成功回调函数
     */
    , tableEnableDisable: function ($, obj, url, ids, callback) {
        let status;
        let msg;
        switch (obj.event) {
            case 'stop':
                status = 1;
                msg = "停用";
                break;
            case 'start':
                status = 2;
                msg = "启用";
                break;
            case 'lock':
                status = 3;
                msg = "锁定";
                break;
        }
        layer.confirm('确定' + msg + '吗？', function () {
            console.log(ids);
            console.log(status);
            $.post(url, {ids: ids, status: status}).then(
                //成功回调
                function (data) {
                    if (data.status === 200) {
                        layer.msg("修改成功");
                    } else if (data.status === 100) {
                        layer.msg("修改失败," + data.message);
                    }
                    if (callback) {
                        callback(data);
                    }
                },
                //失败回调
                function () {
                    layer.msg("请求超时");
                });
        });

    },

    /**
     * 简单的ajax通用处理方法(context-type=appliction/x-www-form-urlencode)
     * @param url
     * @param data json数据
     * @param timeout 重载页面延迟时间，单位：毫秒，0表示不重载页面
     * @param callback 回调处理
     */
    ajaxSimpleUE: function (url, data, timeout, callback) {
        if (zmnUtil.isNull(timeout)) {
            timeout = 0;
        }
        var $ = layui.$;
        $.ajax({
            type: "POST",
            url: url,
            headers: {
                Accept: "application/json"
            },
            timeout: 5000,
            dataType: "json",
            data: data,
            success: function (json) {
                if (timeout) {
                    zmnPage.reload(json.message, timeout);
                }
                if (callback) {
                    callback(json);
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
            }
        });
    },

    /**
     * 简单的ajax通用处理方法(context-type=appliction/json)
     * @param url
     * @param data json数据
     * @param timeout 重载页面延迟时间，单位：毫秒，0表示不重载页面
     * @param callback 回调处理
     */
    ajaxSimpleJson: function (url, data, timeout, callback) {
        if (zmnUtil.isNull(timeout)) {
            timeout = 0;
        }
        var $ = layui.$;
        let shadeIndex;
        $.ajax({
            type: "POST",
            url: url,
            headers: {
                Accept: "application/json"
            },
            timeout: 5000,
            contentType: "application/json",
            dataType: "json",
            data: JSON.stringify(data),
            beforeSend: function () {
                shadeIndex = layer.load(1, {
                    shade: [0.5, '#DBDBDB'] //0.1透明度的白色背景
                });
            },
            success: function (json) {
                layer.close(shadeIndex);
                if (timeout) {
                    zmnPage.reload(json.message, timeout);
                }
                if (callback) {
                    callback(json);
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                layer.close(shadeIndex);
            }
        });
    }
    , ajaxResultDTOJson: function (layer, url, data, timeout, callback, errorCallback) {
        zmnLayUtil.ajaxSimpleJson(url, data, null, function (obj) {
            layer.msg(obj.message);
            if (obj.status == 200) {
                setTimeout(function () {
                    callback(obj);
                }, timeout);
            } else {
                setTimeout(function () {
                    errorCallback(obj);
                }, timeout);
            }
        })
    }
    , ajaxResultDTOUE: function (layer, url, data, timeout, callback, errorCallback) {
        zmnLayUtil.ajaxSimpleUE(url, data, null, function (obj) {
            layer.msg(obj.message);
            if (obj.status == 200) {
                setTimeout(function () {
                    callback(obj);
                }, timeout);
            } else {
                setTimeout(function () {
                    errorCallback(obj);
                }, timeout);
            }
        })
    }
};

let zmnRegularExpressionUtil = {
    /** Integer 最大位数 */
    MAXLENGTH_INTEGER: 9,
    /** Long 最大位数 */
    MAXLENGTH_LONG: 18,
    /** 约定的 金额 最大位数 */
    MAXLENGTH_PRICE: 10,
    /** 约定的 数量 最大位数 */
    MAXLENGTH_NUMBER: 7,
    /**
     * 传入最大位数
     * @param num       需验证的数
     * @param maxlength 最大长度
     */
    maxlengthPrice: function (num, maxlength) {
        if (!this.isAmount(num)) {
            return false;
        }
        return (num + "").replace('.', '').length <= maxlength;
    },
    /**
     * 传入最大位数
     * @param num       需验证的数
     * @param maxlength 最大长度
     */
    maxlengthNumber: function (num, maxlength) {
        if (!this.isNonNegativeInteger(num)) {
            return false;
        }
        return (num + "").length <= maxlength;
    },
    /**
     * 判断传入值是否为正两位小数包含0
     * 用于验证金额
     * @param num
     */
    isAmount: function (num) {
        let r = /^([1-9]\d{0,9}|0)([.]?|(\.\d{1,2})?)$/;
        return r.test(num);
    },
    /**
     * 判断传入值是否为正两位小数
     * 用于验证金额
     * @param num
     */
    isAmountNoZero: function (num) {
        let r = /^(([1-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/;
        return r.test(num);
    },
    /**
     * 判断传入值是否为正整数
     * @param num
     */
    isPositiveInteger: function (num) {
        let r = /^[1-9]\d*$/;　　//正整数
        return r.test(num);

    },
    /**
     * 判断传入值是否为非负整数（正整数 + 0）
     * @param num
     */
    isNonNegativeInteger: function (num) {
        let r = /^\d+$/　　//非负整数（正整数 + 0）
        return r.test(num);
    },
    /**
     * 判断传入值是否为整数
     * @param num
     */
    isInteger: function (num) {
        let r = /^-?\d+$/;　　//整数
        return r.test(num);
    },
    /**
     * 判断传入值是否为正浮点数
     * @param num
     */
    isPositiveFloat: function (num) {
        let r = /^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$/;　//正浮点数
        return r.test(num);
    },
    /**
     * 判断传入值是否为非负浮点数
     * @param num
     */
    isNonNegativeFloat: function (num) {
        let r = /^\d+(\.\d+)?$/; //非负浮点数（正浮点数 + 0）
        return r.test(num);
    },
    /**
     * 判断传入值是否为浮点数
     * @param num
     */
    isFloat: function (num) {
        let r = /^(-?\d+)(\.\d+)?$/;　//浮点数
        return r.test(num);
    },
    /**
     * 判断传入值是否为手机号
     * @param num
     */
    isPhone: function (num) {
        let r = /^1[3456789]\d{9}$/;
        return r.test(num);
    },
    isBankCardNum: function (num) {
        let r = /^([1-9]{1})(\d{14}|\d{18})$/;
        return r.test(num);
    }


};

let zmnImageUtil = {
    /**
     * 描述: 图片插件渲染
     * @param elemId 页面标记的ID，此元素将被替换为图片插件
     * @param imageParam 图片展示参数
     * @param uploadParam 图片上传参数
     */
    uploaderImageRender: function (elemId, imageParam, uploadParam) {
        uploadParam = (uploadParam) ? uploadParam : {enable: false};
        let {suffix = "", enable = true} = uploadParam;
        let newUpdateBtn = zmnImageUtil.uploaderImageDivRender(elemId, imageParam, enable);
        if (enable) zmnImageUtil.uploaderImageListener(newUpdateBtn, uploadParam);
    },
    /**
     * 描述: 图片插件Html渲染方法
     * @param elemId 页面标记的ID，此元素将被替换为图片插件
     * @param imageParam 图片展示参数
     * @param enableUpload 是否开启图片上传
     */
    uploaderImageDivRender: function (elemId, imageParam, enableUpload) {
        imageParam = (imageParam) ? imageParam : {};
        let {imageName, imageUrl, imageTitle = "请指定图片标题"} = imageParam;
        let $elem;
        let baseHtml = `
                    <div class="zmn-upload-div">
                        <div>
                            <div>
                               <h3 class="layui-form-item-p"><b>${imageTitle}</b></h3>
                            </div>
                            <div class="zmn-upload-div-img" data-image="${(imageUrl) ? imageUrl : ''}"></div>
                            <div>
                                <div class="layui-btn-group">
                                    <button type="button" class="layui-btn" id="${imageName}" name="${imageName}">选择图片</button>
                                    <button type="button" class="layui-btn layui-btn-primary" id="${imageName}-upload">上传图片</button>
                                </div>
                            </div>
                        </div>
                    </div>`;
        if (!enableUpload) {
            $elem = $(baseHtml).clone();
            // $elem.remove(".layui-btn-group");
            $elem.find(".layui-btn-group").remove();
        } else {
            $elem = $(baseHtml);
        }

        $("#" + elemId).replaceWith($elem);
        return imageName;
    },
    /**
     * 描述: 图片上传监听
     * @param buttonElemId 需要绑定上传时间的按钮ID
     * @param uploadParam 图片上传插件参数
     */
    uploaderImageListener: function (buttonElemId, uploadParam) {

        let {enable = true, url = "", upload = window.layui.upload} = uploadParam;
        let $divP = $('#' + buttonElemId).closest('.zmn-upload-div').find(".zmn-upload-div-img");
        if (enable) {
            upload.render({
                elem: "#" + buttonElemId
                , auto: false
                , acceptMime: 'image/jpg, image/png, image/jpeg'
                , accept: "images"
                , bindAction: `#${buttonElemId}-upload`
                , size: 3072
                , url: url
                , choose: function (obj) {
                    //预读本地文件，如果是多文件，则会遍历。(不支持ie8/9)
                    obj.preview(function (index, file, result) {
                        // console.log(index);
                        // console.log(file);
                        // console.log(result);
                        // console.log($divP);
                        $($divP).data("image", result);
                        zmnImageUtil.renderImage(`#${buttonElemId}-upload`);
                    });
                }
                , before: function (obj) {
                    console.log(obj);
                    layer.load();
                }
                , done: function (res) {
                    layer.closeAll('loading');
                    console.log(res);
                    layer.msg(res.message, {
                        icon: res.statusBool ? 1 : 2,
                        time: 2000
                    }, function () {
                    });
                }
                , error: function (index, upload) {
                    layer.closeAll('loading');
                }
            });
        }
    },
    /**
     * 描述: 图片渲染方法
     * @param selector 【可选】图片DIV的选择器
     */
    renderImage: function (selector) {

        function render(elem) {
            let $divP = $(elem).closest('.zmn-upload-div').find(".zmn-upload-div-img")
            // 增加随机参数t,解决配件图片缓存
            let imgurl = $divP.data("image");
            if (imgurl === "" || imgurl === undefined) {
                $divP.html("请上传图片");
            } else {
                $divP.html(" ");
                if(imgurl.indexOf('https://') >= 0 || imgurl.indexOf('http://') >= 0){
                    $divP.css("background-image", `url("${imgurl}?t=${Math.random()}")`);
                }else{
                    $divP.css("background-image", `url("${imgurl}")`);
                }
            }
        }

        if (selector) {
            render(selector);
        } else {
            $(".zmn-upload-div").each(function (index, elem) {
                render(elem);
            });
        }
    },
    /**
     * 描述: 图片展示层监听
     * @param $imageElem 图片DIV的选择器
     */
    layerImageListener: function ($imageElem) {
        $imageElem.on("click", function () {
            layer.photos({
                photos: {
                    "title": "", //相册标题
                    "id": 123, //相册id
                    "start": 0, //初始显示的图片序号，默认0
                    "data": $(imageElemSelector).data("image")
                }
                , anim: 5 //0-6的选择，指定弹出图片动画类型，默认随机（请注意，3.0之前的版本用shift参数）
            });
        });
    },
    layerImageRender: function (param = new zmnImageUtil.PicLayerRenderParam()) {

        param = new zmnImageUtil.PicLayerRenderParam(param.imgList, param.albumSetting);
        param.imgList = param.imgList.filter(value => value !== "")
            .map(img => {
                img = new zmnImageUtil.PicLayerRenderParamImg(img.imgName, img.imgId, img.imgSrc, img.thumbimgSrc);
                return {
                    alt: img.imgName,
                    pid: img.imgId, //图片id
                    src: img.imgSrc, //原图地址
                    thumb: (img.thumbimgSrc) ? img.thumbimgSrc : undefined //缩略图地址
                }
            });
        let albumSetting = new zmnImageUtil.PicLayerRenderParamAlbumSetting(param.albumSetting.title, param.albumSetting.albumId, param.albumSetting.startIndex);
        layer.photos({
            photos: {
                "title": albumSetting.title, //相册标题
                "id": albumSetting.albumId, //相册id
                "start": albumSetting.startIndex, //初始显示的图片序号，默认0
                "data": param.imgList
            }
            , anim: 5 //0-6的选择，指定弹出图片动画类型，默认随机（请注意，3.0之前的版本用shift参数）
        });

    },
    PicLayerRenderParam: class PicLayerRenderParam {
        constructor(imgList, albumSetting) {
            this.imgList = imgList;
            this.albumSetting = albumSetting ? albumSetting : new zmnImageUtil.PicLayerRenderParamAlbumSetting();
        }

    },

    PicLayerRenderParamImg: class PicLayerRenderParamImg {
        constructor(imgName, imgId, imgSrc, thumbimgSrc) {
            this.imgName = imgName;
            this.imgId = imgId;
            this.imgSrc = imgSrc;
            this.thumbimgSrc = thumbimgSrc;
        }
    },

    PicLayerRenderParamAlbumSetting: class PicLayerRenderParamAlbumSetting {
        constructor(title, albumId, startIndex) {
            this.title = title ? title : "";
            this.albumId = albumId ? albumId : Math.floor(Math.random() * 10000);
            this.startIndex = startIndex ? startIndex : 0;
        }
    }

};

let zmnUploadUtil = {
    /**
     * 描述：layui 固定格式文件上传接口
     *
     * @param $ jq对象
     * @param upload layui 上传对象 必须从调用js 中传递，否者会出现初始化失败的问题
     * @param elemId 上传框，文件的元素id
     * @param valueId 需要赋值的input的id
     * @param url 上传的url 连接
     * @param parameter 可选参数，
     */
    uploaderImage: function ($, upload, elemId, valueId, url, parameter) {

        if (parameter !== undefined) {
            let {size, acceptMime, accept, exts, callback} = parameter;
        }
        let defaultParameter = {
            size: 3072
            , acceptMime: 'image/*'
            , accept: 'images'
            , exts: 'jpg|png|jpeg'
            , callback: undefined
        };

        let normalParameter = Object.assign({}, defaultParameter, parameter);
        let index;
        upload.render({
            elem: '#' + elemId
            , exts: normalParameter.exts
            , accept: normalParameter.accept
            , acceptMime: normalParameter.acceptMime
            , size: normalParameter.size
            , url: url + '&elemId=' + elemId
            , before: function (obj) {
                index = layui.layer.load(1, {
                    shade: [0.5, '#DBDBDB']
                });
            }, choose: function (obj) {
                //预读本地文件，如果是多文件，则会遍历。(不支持ie8/9)
                obj.preview(function (index, file, result) {
                    $("#" + elemId).attr("style", "background:url( " + result + ");background-size:100% 100%;background-repeat:no-repeat;");
                    let next = $("#" + valueId).next();
                    let next1 = $(next).next();
                    $(next).attr("style", "visibility:hidden !important");
                    $(next1).attr("style", "visibility:hidden !important");
                });
            }
            , done: function (res) {
                if (res.code === 2) {
                    $("#" + valueId).val(res.data.src);
                    if (normalParameter.callback) {
                        normalParameter.callback();
                    }
                } else {
                    layui.layer.msg("上传失败！")
                }
                layui.layer.close(index);
            }
        });
    },
    /**
     *描述：页面加载时回显图片方法
     *
     * @param $ jq对象
     * @param elemId 上传框，文件的元素id
     * @param value 需要回显的值
     * @param valueId 需要赋值的input的id
     */
    reLoadImage: function ($, elemId, value, valueId) {
        if (value !== "" && value != null) {
            $("#" + elemId).attr("style", "background:url( " + value + ");background-size:100% 100%;background-repeat:no-repeat;");
            $("#" + valueId).val(value);
            let next = $("#" + valueId).next();
            let next1 = $(next).next();
            let next2 = $(next1).next();
            $(next).attr("style", "visibility:hidden !important");
            $(next1).attr("style", "visibility:hidden !important");
            $(next2).attr("style", "visibility:hidden !important");
        }
    },
    showBigImg: function (src) {
        layer.photos({
            photos: {
                "data": [
                    {
                        "src": src
                    }
                ]
            },
            anim: 5
        });
    }
};

let zmnButtonUtil = {

    /**
     * 描述: 通过按钮id 禁用按钮
     *
     * @param buttonId 按钮id
     * @param $ jq对象
     * @author wangjie
     * @since 15:31 2019/3/29
     **/
    disabledButton: function (buttonId, $) {
        $('#' + buttonId).attr("disabled", true);
        $("#" + buttonId).addClass("layui-btn layui-btn-disabled").prop("disabled", true);
    },
    /**
     * 描述:通过按钮id 启用按钮
     *
     * @param buttonId 按钮id
     * @param $ jq对象
     * @author wangjie
     * @since 15:33 2019/3/29
     **/
    enableButton: function (buttonId, $) {
        $('#' + buttonId).attr("disabled", false);
        $("#" + buttonId).removeClass("layui-btn-disabled").prop("disabled", false);
    }

};